/**
 * @Author       : Mo 2427995270@qq.com
 * @Date         : 2025-06-07 13:21:32
 * @LastEditTime : 2025-08-17 00:12:01
 * @FilePath     : \ZN-1000-BL\mobl\hal_driver\ll_flash.c
 * @Description  : 片内flash的低层驱动
 * @Version      : V1.0
 * @History      :
 * @Note         :
 */
/***************************************Includes***********************************/
#include "ll_flash.h"

#if defined(GD32F407)
#include "gd32f4xx.h"
#elif defined(STM32F40_41xxx)
#include "stm32f4xx.h"
#elif defined(GD32F10X_HD)
#include "gd32f10x.h"
#elif defined(STM32F10X_HD)
#include "stm32f10x.h"
#elif defined(PY32F071xB)
#include "py32f0xx.h"
#elif defined(STM32F0XX) || defined(STM32F030x6)
#include "stm32f0xx.h"
#else
#error "No device selected"
#endif

/************************************Private Macros********************************/
// #define


/**********************************Private Statement*******************************/

__STATIC_INLINE uint32_t flash_ll_write_gd32f4(uint32_t addr, uint32_t *buf, uint32_t len, uint32_t erase);
__STATIC_INLINE void flash_ll_erase_gd32f4(uint32_t start, uint32_t end);
__STATIC_INLINE uint32_t flash_ll_write_py32f071(uint32_t addr, uint32_t *buf, uint32_t len, uint32_t erase);
__STATIC_INLINE void flash_ll_erase_py32f071(uint32_t start, uint32_t end);
__STATIC_INLINE uint32_t flash_ll_write_stm32f0xx(uint32_t addr, uint32_t *buf, uint32_t len, uint32_t erase);
__STATIC_INLINE void flash_ll_erase_stm32f0xx(uint32_t start, uint32_t end);
/***********************************Public Variables*******************************/



/**********************************Private Variables*******************************/



/**********************************Public Functions********************************/

/**
 * @brief 片内flash写入 带擦除
 * @param  addr             要写入的地址 4字节对齐
 * @param  buf              要写入的数据
 * @param  len              数据的字节数 4的倍数
 * @return uint32_t 写入的字节数
 * @note null
 */
uint32_t flash_ll_write(uint32_t addr, uint32_t *buf, uint32_t len) {
    uint32_t ret = 0;
    if (len & 0b11) { // 未对齐
        return 0;
    }
    if (addr & 0b11) { // 未对齐
        return 0;
    }

#if defined(GD32F407)
    ret = flash_ll_write_gd32f4(addr, buf, len, 1);
#elif defined(STM32F40_41xxx)
#error "未实现"
#elif defined(GD32F10X_HD)
#error "未实现"
#elif defined(STM32F10X_HD)
#error "未实现"
#elif defined(PY32F071xB)
    ret = flash_ll_write_py32f071(addr, buf, len, 1);
#elif defined(STM32F0XX) || defined(STM32F030x6)
    ret = flash_ll_write_stm32f0xx(addr, buf, len, 1);
#endif
    return ret;
}
/**
 * @brief 片内flash写入 不擦除
 * @param  addr             要写入的地址 4字节对齐
 * @param  buf              要写入的数据
 * @param  len              数据的字节数 4的倍数
 * @return uint32_t 写入的字节数
 * @note null
 */
uint32_t flash_ll_write_no_erase(uint32_t addr, uint32_t *buf, uint32_t len) {
    uint32_t ret = 0;
    if (len & 0b11) { // 未对齐
        return 0;
    }
    if (addr & 0b11) { // 未对齐
        return 0;
    }

#if defined(GD32F407)
    ret = flash_ll_write_gd32f4(addr, buf, len, 0);
#elif defined(STM32F40_41xxx)
#error "未实现"
#elif defined(GD32F10X_HD)
#error "未实现"
#elif defined(STM32F10X_HD)
#error "未实现"
#elif defined(PY32F071xB)
    ret = flash_ll_write_py32f071(addr, buf, len, 0);
#elif defined(STM32F0XX) || defined(STM32F030x6)
    ret = flash_ll_write_stm32f0xx(addr, buf, len, 0);
#endif
    return ret;
}

/**
 * @brief 片内flash读取
 * @param  addr             要读取的地址 不需对齐，但性能较低
 * @param  buf              要读取数据的buf
 * @param  len              数据的字节数 4的倍数
 * @return uint32_t 读取的字节数
 * @note null
 */
uint32_t flash_ll_read(uint32_t addr, uint32_t *buf, uint32_t len) {
    for (size_t i = 0; i < len >> 2; i++) {
        buf[i] = ((volatile uint32_t *)addr)[i];
    }
    return len;
}
/**
 * @brief 擦除扇区
 * @param  start            起始地址
 * @param  end              结束地址
 * @note 地址需4字节对齐
 */
void flash_ll_erase(uint32_t start, uint32_t end) {
#if defined(GD32F407)
    flash_ll_erase_gd32f4(start, end);
#elif defined(STM32F40_41xxx)
#error "未实现"
#elif defined(GD32F10X_HD)
#error "未实现"
#elif defined(STM32F10X_HD)
#error "未实现"
#elif defined(PY32F071xB)
    flash_ll_erase_py32f071(start, end);
#elif defined(STM32F0XX) || defined(STM32F030x6)
    flash_ll_erase_stm32f0xx(start, end);
#endif
}

/**********************************Private Functions*******************************/

__STATIC_INLINE uint32_t flash_ll_write_gd32f4(uint32_t addr, uint32_t *buf, uint32_t len, uint32_t erase) {
    uint32_t ret = 0;
#ifdef GD32F4XX_FMC_H
#define BS(KB) KB * 1024
#define HEAD_ADDR 0x08000000
#define B0 HEAD_ADDR + 0
#define B1 B0 + BS(16)
#define B2 B1 + BS(16)
#define B3 B2 + BS(16)
#define B4 B3 + BS(16)
#define B5 B4 + BS(64)
#define B6 B5 + BS(128)
#define B7 B6 + BS(128)
#define B8 B7 + BS(128)
#define B9 B8 + BS(128)
#define B10 B9 + BS(128)
#define B11 B10 + BS(128)
#define B12 B11 + BS(16)
#define B13 B12 + BS(16)
#define B14 B13 + BS(16)
#define B15 B14 + BS(16)
#define B16 B15 + BS(64)
#define B17 B16 + BS(128)
#define B18 B17 + BS(128)
#define B19 B18 + BS(128)
#define B20 B19 + BS(128)
#define B21 B20 + BS(128)
#define B22 B21 + BS(128)
#define B23 B22 + BS(128)

    fmc_unlock();
    fmc_flag_clear(FMC_FLAG_PGSERR);
    uint32_t i = 0;
    for (; i < len / 4; i++) {
        // clang-format off
        if (erase) {
            switch (addr)
            {
            case B0: fmc_sector_erase(CTL_SECTOR_NUMBER_0); break;
            case B1: fmc_sector_erase(CTL_SECTOR_NUMBER_1); break;
            case B2: fmc_sector_erase(CTL_SECTOR_NUMBER_2); break;
            case B3: fmc_sector_erase(CTL_SECTOR_NUMBER_3); break;
            case B4: fmc_sector_erase(CTL_SECTOR_NUMBER_4); break;
            case B5: fmc_sector_erase(CTL_SECTOR_NUMBER_5); break;
            case B6: fmc_sector_erase(CTL_SECTOR_NUMBER_6); break;
            case B7: fmc_sector_erase(CTL_SECTOR_NUMBER_7); break;
            case B8: fmc_sector_erase(CTL_SECTOR_NUMBER_8); break;
            case B9: fmc_sector_erase(CTL_SECTOR_NUMBER_9); break;
            case B10: fmc_sector_erase(CTL_SECTOR_NUMBER_10); break;
            case B11: fmc_sector_erase(CTL_SECTOR_NUMBER_11); break;
            case B12: fmc_sector_erase(CTL_SECTOR_NUMBER_12); break;
            case B13: fmc_sector_erase(CTL_SECTOR_NUMBER_13); break;
            case B14: fmc_sector_erase(CTL_SECTOR_NUMBER_14); break;
            case B15: fmc_sector_erase(CTL_SECTOR_NUMBER_15); break;
            case B16: fmc_sector_erase(CTL_SECTOR_NUMBER_16); break;
            case B17: fmc_sector_erase(CTL_SECTOR_NUMBER_17); break;
            case B18: fmc_sector_erase(CTL_SECTOR_NUMBER_18); break;
            case B19: fmc_sector_erase(CTL_SECTOR_NUMBER_19); break;
            case B20: fmc_sector_erase(CTL_SECTOR_NUMBER_20); break;
            case B21: fmc_sector_erase(CTL_SECTOR_NUMBER_21); break;
            case B22: fmc_sector_erase(CTL_SECTOR_NUMBER_22); break;
            case B23: fmc_sector_erase(CTL_SECTOR_NUMBER_23); break;
            }
        }
        // chang-format on
        uint32_t *ptr = buf;
        fmc_word_program(addr, ptr[i]);
        addr += sizeof(uint32_t);
    }
    ret = i * sizeof(uint32_t);
__exit:
    fmc_lock();
#endif
    return ret;
}

__STATIC_INLINE void flash_ll_erase_gd32f4(uint32_t start, uint32_t end) {
    uint32_t ret = 0;
#ifdef GD32F4XX_FMC_H
    fmc_unlock();
    fmc_flag_clear(FMC_FLAG_PGSERR);
    for (uint32_t i = start; i < end; i += 4) {
        // clang-format off
        switch (i)
        {
        case B0: fmc_sector_erase(CTL_SECTOR_NUMBER_0); break;
        case B1: fmc_sector_erase(CTL_SECTOR_NUMBER_1); break;
        case B2: fmc_sector_erase(CTL_SECTOR_NUMBER_2); break;
        case B3: fmc_sector_erase(CTL_SECTOR_NUMBER_3); break;
        case B4: fmc_sector_erase(CTL_SECTOR_NUMBER_4); break;
        case B5: fmc_sector_erase(CTL_SECTOR_NUMBER_5); break;
        case B6: fmc_sector_erase(CTL_SECTOR_NUMBER_6); break;
        case B7: fmc_sector_erase(CTL_SECTOR_NUMBER_7); break;
        case B8: fmc_sector_erase(CTL_SECTOR_NUMBER_8); break;
        case B9: fmc_sector_erase(CTL_SECTOR_NUMBER_9); break;
        case B10: fmc_sector_erase(CTL_SECTOR_NUMBER_10); break;
        case B11: fmc_sector_erase(CTL_SECTOR_NUMBER_11); break;
        case B12: fmc_sector_erase(CTL_SECTOR_NUMBER_12); break;
        case B13: fmc_sector_erase(CTL_SECTOR_NUMBER_13); break;
        case B14: fmc_sector_erase(CTL_SECTOR_NUMBER_14); break;
        case B15: fmc_sector_erase(CTL_SECTOR_NUMBER_15); break;
        case B16: fmc_sector_erase(CTL_SECTOR_NUMBER_16); break;
        case B17: fmc_sector_erase(CTL_SECTOR_NUMBER_17); break;
        case B18: fmc_sector_erase(CTL_SECTOR_NUMBER_18); break;
        case B19: fmc_sector_erase(CTL_SECTOR_NUMBER_19); break;
        case B20: fmc_sector_erase(CTL_SECTOR_NUMBER_20); break;
        case B21: fmc_sector_erase(CTL_SECTOR_NUMBER_21); break;
        case B22: fmc_sector_erase(CTL_SECTOR_NUMBER_22); break;
        case B23: fmc_sector_erase(CTL_SECTOR_NUMBER_23); break;
        }
        // chang-format on
    }
    fmc_lock();
#endif
}

__STATIC_INLINE uint32_t flash_ll_write_py32f071(uint32_t addr, uint32_t *buf, uint32_t len, uint32_t erase) {
    uint32_t i = 0;
#if defined(PY32F071xB)
    uint32_t page_offset = addr % 256; // 地址在页内偏移
    uint32_t page_free = 256 - page_offset; // 当前页剩余空间
    uint32_t page_addr = addr - page_offset; // 当前页地址
    uint32_t size = len > page_free ? page_free : len;
    uint32_t page_data[64]; // 当前页数据 256bytes
    HAL_FLASH_Unlock();

    uint32_t PAGEError = 0;
    FLASH_EraseInitTypeDef EraseInitStruct = {0};
    EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGEERASE;
    EraseInitStruct.NbPages = 1;
    
    for (i = 0; i < len; ) {
        // 拷贝当前页数据
        for (uint32_t j = 0; j < sizeof(page_data) / sizeof(page_data[0]); j++) {
            page_data[j] = ((volatile uint32_t*)page_addr)[j];
        }
        EraseInitStruct.PageAddress = page_addr;
        if (erase) {
            if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {
                goto __exit;
            }
        }
        for (uint32_t k = 0; k < size; k += 4) {
            page_data[(page_offset + k) >> 2] = *buf;
            buf++;
        }
        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_PAGE, page_addr, page_data) != HAL_OK) {
            goto __exit;
        }
        if (i == len) {
            goto __exit;
        }
        i += size;
        page_addr += 256;
        page_offset = 0;
        size = len - i > 256 ? 256 : len - i;
    }
    
__exit:
    HAL_FLASH_Lock();
#endif
    return i;
}

__STATIC_INLINE void flash_ll_erase_py32f071(uint32_t start, uint32_t end) {
#if defined(PY32F071xB)
    HAL_FLASH_Unlock();

    uint32_t PAGEError = 0;
    FLASH_EraseInitTypeDef EraseInitStruct = {0};
    EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGEERASE;
    EraseInitStruct.NbPages = 1;
    
    for (uint32_t i = start; i < end; i += 4) {
        if(i % 256 == 0) {
            EraseInitStruct.PageAddress = i;
            if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {
                goto __exit;
            }
        }
    }
    
__exit:
    HAL_FLASH_Lock();
#endif
}

__STATIC_INLINE uint32_t flash_ll_write_stm32f0xx(uint32_t addr, uint32_t *buf, uint32_t len, uint32_t erase) {
#if defined(STM32F0XX) || defined(STM32F030x6)
#error "未实现"
#endif
    return 0;
}

__STATIC_INLINE void flash_ll_erase_stm32f0xx(uint32_t start, uint32_t end) {
#if defined(STM32F0XX) || defined(STM32F030x6)
#error "未实现"
#endif
}

/* [] END OF FILE */
